use serde::{Deserialize, Serialize};


#[derive(Debug, Serialize, Deserialize)]
pub struct WorkerJobOutput {
    pub pre: Vec<PreWorkerJob>,
    pub commit: Vec<CommitWorkerJob>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PreWorkerJob {
    pub id: String,
    pub host: String,
    pub enable: bool,
    pub add_piece: JobOverview,
    pub pre_one: JobOverview,
    pub pre_two: JobOverview,
    pub commit: JobOverview,
    pub finalize: JobOverview,
    pub fetch: JobOverview,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct CommitWorkerJob {
    pub id: String,
    pub host: String,
    pub enable: bool,
    pub commit: JobOverview,
    pub finalize: JobOverview,
    pub fetch: JobOverview,
}

#[derive(Default, Debug, Serialize, Deserialize)]
pub struct JobOverview {
    pub limit: u32,
    pub db: JobCount,
    pub miner: JobCount,
}

#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct JobCount {
    pub running: u32,
    pub assigned: u32,
}

impl WorkerJobOutput {
    pub fn new() -> Self {
        WorkerJobOutput {
            pre: Vec::new(),
            commit: Vec::new(),
        }
    }
}

impl PreWorkerJob {
    pub fn new(id: String, host: String, enable: bool, add_piece: JobOverview, pre_one: JobOverview, pre_two: JobOverview, commit: JobOverview, finalize: JobOverview, fetch: JobOverview) -> Self {
        PreWorkerJob{
            id,
            host,
            enable,
            add_piece,
            pre_one,
            pre_two,
            commit,
            finalize,
            fetch,
        }
    }
}

impl CommitWorkerJob {
    pub fn new(id: String, host: String, enable: bool, commit: JobOverview, finalize: JobOverview, fetch: JobOverview) -> Self {
        CommitWorkerJob{
            id,
            host,
            enable,
            commit,
            finalize,
            fetch
        }
    }
}

impl JobOverview {
    pub fn with_data(limit: u32, db: JobCount, miner: JobCount) -> Self {
        JobOverview {
            limit,
            db,
            miner
        }
    }
}

impl JobCount {
    pub fn new(running: u32, assigned: u32) -> Self {
        JobCount {
            running,
            assigned,
        }
    }

    pub fn add_db(&mut self, status: u32) {
        if status == 0 {
            self.assigned = self.assigned + 1
        } else {
            self.running = self.running + 1
        }
    }

    pub fn add_miner(&mut self, status: i32) {
        if status > 0 {
            self.assigned = self.assigned + 1
        } else {
            self.running = self.running + 1
        }
    }
}